﻿using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Web;

namespace PickGold.Base
{
	/// <summary>
	/// Json 生成器接口。
	/// </summary>
	public interface IJsonBuilder
	{
		/// <summary>
		/// 尝试获取扩展属性
		/// </summary>
		/// <param name="name">要尝试获取的属性名称</param>
		/// <param name="value">要尝试获取的属性值，带星号(*)则表示排除列表</param>
		/// <returns>是否获取成功</returns>
		bool TryGetEP(string name, ref object value);
		/// <summary>
		/// 尝试获取扩展属性
		/// </summary>
		/// <param name="key">要尝试获取属性的对象，如果是【Empty】则表示全局扩展</param>
		/// <param name="name">要尝试获取的属性名称</param>
		/// <param name="value">要尝试获取的属性值，带星号(*)则表示排除列表</param>
		/// <returns>是否获取成功</returns>
		bool TryGetEP(object key, string name, ref object value);
		/// <summary>
		/// 获取扩展属性
		/// </summary>
		/// <param name="name">要获取的属性名称，带星号(*)则表示排除列表</param>
		/// <returns>属性值</returns>
		object GetEP(string name);
		/// <summary>
		/// 设置扩展属性
		/// </summary>
		/// <param name="name">要设置的属性名称，如果为空(Empty)字符串表示排除扩展列表，带星号(*)则表示排除列表</param>
		/// <param name="value">要设置的属性值</param>
		/// <returns>属性值</returns>
		object SetEP(string name, object value);
		/// <summary>
		/// 获取扩展属性
		/// </summary>
		/// <param name="key">要获取属性的对象，如果是【Empty】则表示全局扩展，带星号(*)则表示排除列表</param>
		/// <param name="name">要获取的属性名称</param>
		/// <returns>属性值</returns>
		object GetEP(object key, string name);
		/// <summary>
		/// 设置扩展属性
		/// </summary>
		/// <param name="key">要设置属性的对象，如果是【Empty】则表示全局扩展</param>
		/// <param name="name">要设置的属性名称，如果为空(Empty)字符串表示排除扩展列表，带星号(*)则表示排除列表</param>
		/// <param name="value">要设置的属性值</param>
		/// <returns>属性值</returns>
		object SetEP(object key, string name, object value);
		/// <summary>
		/// 添加扩展
		/// </summary>
		/// <param name="name">扩展的成员名称，如果为空(Empty)字符串表示排除扩展列表，带星号(*)则表示排除列表</param>
		/// <param name="value">扩展的成员值</param>
		object AppendEP(string name, object value);
		/// <summary>
		/// 添加扩展
		/// </summary>
		/// <param name="key">扩展的对象</param>
		/// <param name="name">扩展的成员名称，如果为空(Empty)字符串表示排除扩展列表，带星号(*)则表示排除列表</param>
		/// <param name="value">扩展的成员值</param>
		object AppendEP(object key, string name, object value);
		/// <summary>
		/// 类型名称字符串。
		/// </summary>
		string ClassName { get; set; }
		/// <summary>
		/// 变量名
		/// </summary>
		string Variable { get; set; }
		/// <summary>
		/// 要转换的对象
		/// </summary>
		object Graph { get; set; }
		/// <summary>
		/// 忽略错误。
		/// </summary>
		bool IgnoreError { get; set; }
		/// <summary>
		/// 移除扩展
		/// </summary>
		/// <param name="key">扩展的对象</param>
		void RemoveEP(object key);
		/// <summary>
		/// 移除扩展
		/// </summary>
		/// <param name="key">扩展的对象</param>
		/// <param name="name">扩展的成员名称，带星号(*)则表示排除列表</param>
		void RemoveEP(object key, string name);
		/// <summary>
		/// 移除扩展
		/// </summary>
		void RemoveEP();
		/// <summary>
		/// 是否存在扩展
		/// </summary>
		/// <returns></returns>
		bool HasEP();
		/// <summary>
		/// 是否存在根对象扩展
		/// </summary>
		/// <param name="name">根对象扩展名，带星号(*)则表示排除列表</param>
		/// <returns></returns>
		bool HasEP(string name);
		/// <summary>
		/// 判断指定对象是否存在扩展或存在指定名称的扩展
		/// </summary>
		/// <param name="key">对象</param>
		/// <param name="name">指定对象的名称扩展，如果为空则表示指定对象是否存在任意扩展，带星号(*)则表示排除列表</param>
		/// <returns></returns>
		bool HasEP(object key, string name);
		/// <summary>
		/// 设置或获取扩展属性
		/// </summary>
		/// <param name="name">要获取或设置的属性名称，带星号(*)则表示排除列表</param>
		/// <returns>属性值</returns>
		object this[string name] { get; set; }
		/// <summary>
		/// 设置或获取扩展属性
		/// </summary>
		/// <param name="key">要获取或设置属性的对象</param>
		/// <param name="name">要获取或设置的属性名称，带星号(*)则表示排除列表</param>
		/// <returns>属性值</returns>
		object this[object key, string name] { get; set; }
		/// <summary>
		/// 序列化成Json字符串
		/// </summary>
		/// <param name="output"></param>
		/// <returns>是否已有Json生成，如果为零表示没有任何数据生成。</returns>
		int Render(TextWriter output);
		/// <summary>
		/// 输入指定对象的Json字符流
		/// </summary>
		/// <param name="output">Json书写器</param>
		/// <param name="graph">要输出的对象</param>
		/// <param name="stack">防止序列化死递归的堆对象</param>
		/// <param name="path">防止序列化死递归的引用路径</param>
		/// <param name="flags">指示序列化成员的标志</param>
		/// <param name="prefix">前缀字符串</param>
		/// <returns>是否已输出，为零表示没有任何输出，需要生成器继续处理。</returns>
		int Render(TextWriter output, object graph, IDictionary<object, string> stack, string path, BindingFlags flags, string prefix);
		/// <summary>
		/// 设置变量名
		/// </summary>
		/// <param name="parent">父变量名，如果为“/”则为“window”对象</param>
		/// <param name="variable">变量名</param>
		/// <returns>变量名</returns>
		string SetVariable(string parent, string variable);
		/// <summary>
		/// 设置变量名
		/// </summary>
		/// <param name="parent">父变量名，如果为“/”则为“window”对象</param>
		/// <param name="var0">变量名，如果为空，则为“var1”的值</param>
		/// <param name="var1">变量名</param>
		/// <returns>变量名</returns>
		string SetVariable(string parent, string var0, string var1);
		/// <summary>
		/// 设置变量名
		/// </summary>
		/// <param name="parent">父变量名，如果为“/”则为“window”对象</param>
		/// <param name="var0">变量名，如果为空，则为“var1”的值</param>
		/// <param name="var1">变量名，如果为空，则为“var2”的值</param>
		/// <param name="var2">变量名</param>
		/// <returns>变量名</returns>
		string SetVariable(string parent, string var0, string var1, string var2);
		/// <summary>
		/// 序列化成Json字符串
		/// </summary>
		/// <param name="bindingFlags">指示序列化成员的标志</param>
		/// <returns>用Json表示对象的字符串</returns>
		string ToString(BindingFlags bindingFlags);
		/// <summary>
		/// 序列化成Json字符串
		/// </summary>
		/// <param name="staticMember">是否成生静态成员对象</param>
		/// <returns>用Json表示对象的字符串</returns>
		string ToString(bool staticMember);
		/// <summary>
		/// 序列化成Json字符串
		/// </summary>
		/// <returns>用Json表示对象的字符串</returns>
		string ToString();
	}

	/// <summary>
	/// 可 Json 序列化支持接口
	/// </summary>
	public interface IJsonSerializable
	{
		/// <summary>
		/// 返回输入成员，可以是成员属性也可以是成员字段，如果为空或长度为零则表示当前对象无需序列化
		/// </summary>
		/// <param name="json">要序列化的 Json 对象</param>
		/// <param name="path">序列化路径</param>
		/// <param name="flags">应返回的成员的搜索标志</param>
		/// <returns>需要输出的成员列表</returns>
		MemberInfo[] GetMembers(IJsonBuilder json, string path, BindingFlags flags);
	}
}
